package main

import (
	"fmt"
	"sync"
)

func main() {
	/*
		在 循环迭代器变量 上使用 goroutine 所引发的问题
			输出该变量，结果会出现很多相同的值（这些相同的值不一定相同）。

		原因：
			1.整个循环中，循环迭代器变量 只定义了一个，其每一次循环只是简单的将 值 拷贝 到 该变量的地址处，
		    所以 for range（for 循环）中，对 value（i）取地址操作没有任何意义!!!

			2.在 Go语言中，“变量在跨作用域时会被传递”，这种特性也被称为“闭包”。

			在此问题中，由于 goroutine 创建的过程是异步的，所以当它们开始执行时，循环就已经完成了，并且变量 v 已经被赋值为最后一个元素的值。
			因此，在每个 goroutine 中访问变量 v 时，它们都读取了相同的最后一个元素的值。

		解决方案：可以通过将变量 v 作为参数传递给 goroutine 来创建一个本地副本。这样，每个 goroutine 都将拥有自己的变量的副本，并不会互相干扰。
			注：
				goroutine 捕获变量和 goroutine执行是异步的。
				当一个 goroutine 被创建后，它会捕获 当前可用的值 来初始化 所引用的变量，然后在后台运行。
				因为 goroutine 是并发执行的，所以在捕获变量后，被捕获这些的变量的值可能会随着时间的推移而改变。
				此外，每个 goroutine 都有自己的堆栈空间，因此对共享变量的访问必须进行同步以避免竞争条件。
				因此，如果多个 goroutine 同时访问同一变量，则需要采用适当的同步措施来避免竞争条件和数据竞争等问题。
	*/
	nums := []int{1, 2, 3}
	wg := sync.WaitGroup{}
	wg.Add(len(nums))
	for _, num := range nums {
		go func() {
			defer wg.Done()
			fmt.Println(num)
		}()
	}
	wg.Wait()
	/*结果：
	3
	3
	3
	*/
	/*
		解决方案：
			nums := []int{1, 2, 3}
			wg := sync.WaitGroup{}
			wg.Add(len(nums))
			for _, num := range nums {
				t := num
				go func() {
					defer wg.Done()
					fmt.Println(t)
				}()
			}
			wg.Wait()
			//结果：1,2,3 以不确定的顺序依次输出，每次的结果都不一定
	*/
}
